儲存資料有許多方式,其中Database 最為常見,google 提供儲存本地端資料 library Room ,建立 Database,在SQLite上提供了一個抽象層,能夠流暢地訪問資料庫。
使用方式為:
import Room persistence library
def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
Room 包含 3 個主要元件:
Database :資料庫持有者與提供資料連結的關聯式資料庫
Entity:表示資料庫的table。
DAO:包含用於訪問資料庫的方法
以下為實作方式:
Database
建立DB entities代表 Todos table
@Database(
version = 1,
entities = [
Todos::class
],
exportSchema = false
)
abstract class AppDatabase: RoomDatabase() {
companion object {
private const val DATABASE_NAME = "todo_db"
// For Singleton instantiation
@Volatile private var instance: AppDatabase? = null
fun getInstance(context: Context): AppDatabase {
return instance ?: synchronized(this) {
instance ?: buildDatabase(context).also { instance = it }
}
}
database 建立
private fun buildDatabase(context: Context): AppDatabase {
return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME).build()
}
}
abstract fun todoItemDao(): ItemsDao
}
Entity
建立table
@Entity(
tableName = Items.TABLE_NAME
)
data class Items (
@ColumnInfo(name = COLUMN_TITLE) var title: String,
@ColumnInfo(name = COLUMN_DONE) var done: Boolean,
@ColumnInfo(name = COLUMN_CREATED_Date) var createdDate: Date
) {
companion object {
const val TABLE_NAME = "items"
const val COLUMN_ID = "id"
const val COLUMN_TITLE = "title"
const val COLUMN_DONE = "done"
const val COLUMN_CREATED_AT = "created_date"
}
//主鍵為一值
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = COLUMN_ID) var id: Int = 0
}
Dao
data Access objc 與DB存取刪除動作物件。
建立泛型之後要使用table 繼承後就可以實作新增刪修
interface GenericDao<T> {
@Insert
suspend fun insert(obj: T)
@Insert
suspend fun insert(vararg obj: T)
@Update
suspend fun update(obj: T)
@Delete
suspend fun delete(obj: T)
}
@Dao
interface ItemsDao: GenericDao<Items> {
@Query("SELECT * FROM ${Items.TABLE_NAME} ORDER BY ${Items.COLUMN_CREATED_AT} DESC")
fun findAll(): List<TodoItemDao>
}
class ItemaRepository(
private val database: AppDatabase
) {
fun insertTodoItem(todoItem: TodoItem) {
database.itemsDao().insert(todoItem)
}
}
}
ViewModel
class TodoViewModel(private val repository: ItemaRepository) : ViewModel() {
val onNewTodo = MutableLiveData<String>()
val todoLiveData: LiveData<List<Todo>> = MediatorLiveData<List<Todo>>().apply {
addSource(onNewTodo) { text ->
val todo = Todo.Item(text, false)
this.value = this.value!! + listOf(todo)
}
value = mutableListOf(Todo.Title("This is a title"))
fun createNewTodo(title: String) {
val todoItem = TodoItem(
title = title,
done = false,
createdDate = Date()
)
repository.insertTodoItem(todoItem)
}
}
UI 呼叫 TodoViewModel 做 createNewTodo
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val itemsDb = AppDatabase.getInstance(requireActivity().applicationContext)
val itemsRepo = TodoItemRepository(todoItemDb)
val todoViewModel = ViewModelProvider(requireActivity(), viewModelFactory).get(TodoViewModel::class.java)
//新增資料
todoViewModel.createNewTodo(title)
}
reference:https://www.notion.so/Storage-9-23-Cateyes-7e968a1aa22a48d49b0c79089a9ed651
reference:https://developer.android.com/training/data-storage
reference:https://developer.android.com/training/data-storage/room/accessing-data
reference:https://developer.android.com/reference/android/arch/lifecycle/ViewModelProviders